package com.example.yian.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.example.yian.entity.*;
import com.example.yian.mapper.TextSearchRequestMapper;
import com.example.yian.mapper.TextSearchResponseMapper;
import com.example.yian.mapper.UserMapper;
import com.example.yian.service.TextSearchService;
import com.example.yian.service.WeChatAuthService;
import com.example.yian.util.JwtUtils;
import com.fasterxml.jackson.core.ObjectCodec;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import io.jsonwebtoken.Claims;
import org.apache.catalina.core.ApplicationContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.io.IOException;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.Instant;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionException;
import java.util.concurrent.ConcurrentHashMap;
import java.time.Duration;
import java.util.concurrent.ExecutionException;

@Component
public class ChatWebSocketHandler extends TextWebSocketHandler {

    private static ConfigurableApplicationContext applicationContext;

    private static TextSearchService textSearchService;

    private static WeChatAuthService weChatAuthService;

    private static String strNewApiKey = "application-1dabbbdbf2be09c946ef401ca2412fdb";

    private static String strNewChatId = "c95507ba-93a4-11ef-a11d-0242ac110002";

    private static String strOldApiKey = "application-8900dd45b50a0e7d2b06bef61c526df0";

    private static String strOldChatId = "2f611eda-93a6-11ef-ad48-0242ac110002";

    private TextSearchRequestMapper textSearchRequestMapper;

    private TextSearchResponseMapper textSearchResponseMapper;

    private UserMapper userMapper;

    private StringBuilder accumulatedContent = new StringBuilder();

    private static final Logger log = LoggerFactory.getLogger(ChatWebSocketHandler.class);

    public ChatWebSocketHandler() {
        // 直接实例化 TextSearchService
        textSearchService = new TextSearchService();
        weChatAuthService = new WeChatAuthService();
    }

    public static void setApplicationContext(ConfigurableApplicationContext context) {
        applicationContext = context;
    }

    private final ConcurrentHashMap<String, WebSocketSession> sessions = new ConcurrentHashMap<>();

    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        sessions.put(session.getId(), session);

        // 添加连接成功后的响应处理
        try {
            // 发送欢迎消息到客户端
            String welcomeMessage = "欢迎！您已成功连接到聊天服务器。";
            session.sendMessage(new TextMessage(welcomeMessage));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        // 处理前端发送的消息，调用 SSE 接口并转发结果
        String payload = message.getPayload();
        // 解析 payload，调用 SSE 接口
        sendSSEToWebSocket(session, payload);
    }

    private void sendSSEToWebSocket(WebSocketSession session, String payload) throws IOException {
        // 调用 SSE 接口，获取流式响应
        // 假设 SSE 接口的 URL 和参数已经解析
        String sseUrl = "";
        String strApiKey = "";

        ObjectMapper objectMapper = new ObjectMapper();
        ChatMessage chatMessage = objectMapper.readValue(payload, ChatMessage.class);

        // 提取 text_message 和 is_save 字段
        String textMessage = chatMessage.getTextMessage();
        boolean isSave = chatMessage.getIsSave();
        String strToken = chatMessage.getAuthorization();

        if(isSave)
        {
            log.info("enter 安全专家 process!");
            sseUrl = "http://120.26.5.41:8080/api/application/chat_message/" + strOldChatId;
            strApiKey = strOldApiKey;
        }
        else {
            log.info("enter 工地助手 process!");
            sseUrl = "http://120.26.5.41:8080/api/application/chat_message/" + strNewChatId;
            strApiKey = strNewApiKey;
        }

        //根据token获取userId
        Optional<Long> userIdOpt ;
        try {
            Claims claims = JwtUtils.parseToken(strToken);
            String openid = claims.getSubject();
            QueryWrapper<User> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("openid", openid);
            userMapper = applicationContext.getBean(UserMapper.class);
            User user = userMapper.selectOne(queryWrapper);
            userIdOpt =  Optional.ofNullable(user).map(User::getUserId);
        } catch (Exception e) {
            log.error("sendSSEToWebSocket | parse Token error!");
            return;
        }

        log.info("sendSSEToWebSocket |, userId:{}",userIdOpt.get());

        // 创建请求体
        ObjectNode requestBody = objectMapper.createObjectNode();
        requestBody.put("message", textMessage);
        requestBody.put("re_chat", true);
        requestBody.put("stream", true);
        String strPayload = requestBody.toString();

        // 创建HTTP客户端
        HttpClient httpClient = HttpClient.newHttpClient();

        // 构建请求
        HttpRequest request = HttpRequest.newBuilder()
                .uri(URI.create(sseUrl))
                .header("Content-Type", "application/json")
                .header("Authorization", strApiKey)
                .POST(HttpRequest.BodyPublishers.ofString(strPayload))
                .timeout(Duration.ofSeconds(120)) //设置超时时间2分钟
                .build();

        //保存搜索记录
        TextSearchRequest requestSearch = new TextSearchRequest();
        requestSearch.setTextMessage(textMessage);
        requestSearch.setReChat(true);
        requestSearch.setStream(true);
        requestSearch.setUserId(userIdOpt.get());
        requestSearch.setCreatedAt(LocalDateTime.now());
        requestSearch.setIsSpecificationSearch(isSave);
        textSearchRequestMapper = applicationContext.getBean(TextSearchRequestMapper.class);
        int ret = textSearchRequestMapper.insert(requestSearch);
        if(requestSearch.getId() == 0 )
        {
            log.error("sendSSEToWebSocket | save Request failed, id is zero,ret:{}!", ret);
        }

        log.info("sendSSEToWebSocket | save Request success, id:{}", requestSearch.getId());

        httpClient.sendAsync(request, HttpResponse.BodyHandlers.ofLines())
                .thenAccept(response -> {
                    response.body().forEach(line -> {
                        try {
                            // 解析 SSE 响应
                            if (line.startsWith("data: ")) {
                                String jsonData = line.substring(6);
                                // 解析 JSON 数据
                                String strOriginalContent = "原始字符串:";
                                log.info(strOriginalContent + jsonData);
                                ChatResponse chatResponse = new ObjectMapper().readValue(jsonData, ChatResponse.class);

                                accumulatedContent.append(chatResponse.getContent());
                                if(chatResponse.getIsEnd() == true)
                                {
                                    textSearchResponseMapper = applicationContext.getBean(TextSearchResponseMapper.class);
                                    Optional<TextSearchResponse> textResponseOpt = Optional.ofNullable(textSearchResponseMapper.selectByTextId(chatResponse.getId()));

                                    if (textResponseOpt.isPresent())
                                    {
                                        log.error("ws search TextId can be founded,textId:{}",chatResponse.getId());
                                    }
                                    else
                                    {
                                        log.info("sendSSEToWebSocket | save Response success, id:{}", chatResponse.getId());
                                        saveTextSearchResponse(requestSearch.getId(),chatResponse.getChatId(),chatResponse.getId(),chatResponse.getOperate(),accumulatedContent.toString(),"GB50310电梯工程施工质量验收",true,isSave);
                                    }
                                }
                                ChatFrontResponse chatFrontResponse = convertToChatFrontResponse(chatResponse, String.valueOf(userIdOpt.get()).toString(),requestSearch.getId().toString());
                                // 将解析后的数据发送给前端.
                                TextMessage msg = new TextMessage(chatFrontResponse.toJson());
                                String strMsg = String.valueOf(msg.getPayload());
                                log.info(strMsg);
                                session.sendMessage(new TextMessage(chatFrontResponse.toJson()));
                            }
                        } catch (IOException e) {
                            log.error("sendSSEToWebSocket | parse json error!");
                            e.printStackTrace();
                        }
                    });
                });
    }

    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        sessions.remove(session.getId());
        log.error("ws was closed!");
    }

    private void saveTextSearchResponse(Long RequestId, String chatId, String textId, Boolean operate, String content, String refText, Boolean isEnd, boolean isSave) {
        TextSearchResponse response = new TextSearchResponse();
        response.setRequestId(RequestId);

        response.setChatId(chatId);
        response.setTextId(textId);
        response.setOperate(operate);
        response.setContent(content);
        response.setRefText(refText); // 修改这里
        response.setIsEnd(isEnd);
        response.setCreatedAt(LocalDateTime.now());
        response.setUpdatedAt(LocalDateTime.now());
        if(isSave)
        {
            textSearchResponseMapper = applicationContext.getBean(TextSearchResponseMapper.class);
            textSearchResponseMapper.insert(response);
        }
    }

    public static ChatFrontResponse convertToChatFrontResponse(ChatResponse chatResponse,String userId,String requestId) {
        ChatFrontResponse chatFrontResponse = new ChatFrontResponse();

        // 转换已有的字段
        chatFrontResponse.setContent(chatResponse.getContent());
        chatFrontResponse.setTextId(chatResponse.getId());
        chatFrontResponse.setIsEnd(chatResponse.getIsEnd());
        chatFrontResponse.setRequestId(requestId);
        chatFrontResponse.setChatId(chatResponse.getChatId());
        chatFrontResponse.setRefText("GB50310电梯工程施工质量验收");

        // 补充额外的字段
        chatFrontResponse.setUserId(userId);

        return chatFrontResponse;
    }
}